package com.imut.lagain.util;

import java.util.regex.Pattern;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.nio.charset.StandardCharsets;

/**
 * 验证工具类
 */
public class ValidationUtil {
    
    // 邮箱验证正则表达式
    private static final String EMAIL_PATTERN = 
        "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@" +
        "(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
    
    // 手机号验证正则表达式（中国大陆）
    private static final String PHONE_PATTERN = 
        "^1[3-9]\\d{9}$";
    
    // 用户名验证正则表达式（4-20位字母、数字、下划线）
    private static final String USERNAME_PATTERN = 
        "^[a-zA-Z0-9_]{4,20}$";
    
    // 密码验证正则表达式（8-20位，至少包含字母和数字）
    private static final String PASSWORD_PATTERN = 
        "^(?=.*[a-zA-Z])(?=.*\\d)[a-zA-Z\\d@$!%*?&]{8,20}$";
    
    // 昵称验证正则表达式（2-20位中文、字母、数字）
    private static final String NICKNAME_PATTERN = 
        "^[\\u4e00-\\u9fa5a-zA-Z0-9]{2,20}$";
    
    // 身份证号验证正则表达式
    private static final String ID_CARD_PATTERN = 
        "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
    
    private static final Pattern emailPattern = Pattern.compile(EMAIL_PATTERN);
    private static final Pattern phonePattern = Pattern.compile(PHONE_PATTERN);
    private static final Pattern usernamePattern = Pattern.compile(USERNAME_PATTERN);
    private static final Pattern passwordPattern = Pattern.compile(PASSWORD_PATTERN);
    private static final Pattern nicknamePattern = Pattern.compile(NICKNAME_PATTERN);
    private static final Pattern idCardPattern = Pattern.compile(ID_CARD_PATTERN);
    
    /**
     * 验证邮箱格式
     * @param email 邮箱地址
     * @return 是否有效
     */
    public static boolean isValidEmail(String email) {
        if (email == null || email.trim().isEmpty()) {
            return false;
        }
        return emailPattern.matcher(email.trim()).matches();
    }
    
    /**
     * 验证手机号格式
     * @param phone 手机号
     * @return 是否有效
     */
    public static boolean isValidPhone(String phone) {
        if (phone == null || phone.trim().isEmpty()) {
            return false;
        }
        return phonePattern.matcher(phone.trim()).matches();
    }
    
    /**
     * 验证用户名格式
     * @param username 用户名
     * @return 是否有效
     */
    public static boolean isValidUsername(String username) {
        if (username == null || username.trim().isEmpty()) {
            return false;
        }
        return usernamePattern.matcher(username.trim()).matches();
    }
    
    /**
     * 验证密码格式
     * @param password 密码
     * @return 是否有效
     */
    public static boolean isValidPassword(String password) {
        if (password == null || password.trim().isEmpty()) {
            return false;
        }
        return passwordPattern.matcher(password.trim()).matches();
    }
    
    /**
     * 验证昵称格式
     * @param nickname 昵称
     * @return 是否有效
     */
    public static boolean isValidNickname(String nickname) {
        if (nickname == null || nickname.trim().isEmpty()) {
            return false;
        }
        return nicknamePattern.matcher(nickname.trim()).matches();
    }
    
    /**
     * 验证身份证号格式
     * @param idCard 身份证号
     * @return 是否有效
     */
    public static boolean isValidIdCard(String idCard) {
        if (idCard == null || idCard.trim().isEmpty()) {
            return false;
        }
        
        String cleanIdCard = idCard.trim().toUpperCase();
        if (!idCardPattern.matcher(cleanIdCard).matches()) {
            return false;
        }
        
        // 验证校验码
        return validateIdCardChecksum(cleanIdCard);
    }
    
    /**
     * 验证字符串长度
     * @param str 字符串
     * @param minLength 最小长度
     * @param maxLength 最大长度
     * @return 是否在有效范围内
     */
    public static boolean isValidLength(String str, int minLength, int maxLength) {
        if (str == null) {
            return false;
        }
        int length = str.trim().length();
        return length >= minLength && length <= maxLength;
    }
    
    /**
     * 验证字符串是否为空或null
     * @param str 字符串
     * @return 是否为空
     */
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
    
    /**
     * 验证字符串是否不为空
     * @param str 字符串
     * @return 是否不为空
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }
    
    /**
     * 验证数字范围
     * @param value 数值
     * @param min 最小值
     * @param max 最大值
     * @return 是否在有效范围内
     */
    public static boolean isInRange(int value, int min, int max) {
        return value >= min && value <= max;
    }
    
    /**
     * 验证数字范围
     * @param value 数值
     * @param min 最小值
     * @param max 最大值
     * @return 是否在有效范围内
     */
    public static boolean isInRange(long value, long min, long max) {
        return value >= min && value <= max;
    }
    
    /**
     * 验证数字范围
     * @param value 数值
     * @param min 最小值
     * @param max 最大值
     * @return 是否在有效范围内
     */
    public static boolean isInRange(double value, double min, double max) {
        return value >= min && value <= max;
    }
    
    /**
     * 验证URL格式
     * @param url URL地址
     * @return 是否有效
     */
    public static boolean isValidUrl(String url) {
        if (isEmpty(url)) {
            return false;
        }
        
        String urlPattern = "^(https?|ftp)://[^\\s/$.?#].[^\\s]*$";
        return Pattern.matches(urlPattern, url.trim());
    }
    
    /**
     * 验证IP地址格式
     * @param ip IP地址
     * @return 是否有效
     */
    public static boolean isValidIp(String ip) {
        if (isEmpty(ip)) {
            return false;
        }
        
        String ipPattern = "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$";
        return Pattern.matches(ipPattern, ip.trim());
    }
    
    /**
     * 验证端口号
     * @param port 端口号
     * @return 是否有效
     */
    public static boolean isValidPort(int port) {
        return port > 0 && port <= 65535;
    }
    
    /**
     * 验证年龄
     * @param age 年龄
     * @return 是否有效
     */
    public static boolean isValidAge(int age) {
        return age >= 0 && age <= 150;
    }
    
    /**
     * 验证QQ号
     * @param qq QQ号
     * @return 是否有效
     */
    public static boolean isValidQQ(String qq) {
        if (isEmpty(qq)) {
            return false;
        }
        
        String qqPattern = "^[1-9]\\d{4,10}$";
        return Pattern.matches(qqPattern, qq.trim());
    }
    
    /**
     * 验证微信号
     * @param wechat 微信号
     * @return 是否有效
     */
    public static boolean isValidWechat(String wechat) {
        if (isEmpty(wechat)) {
            return false;
        }
        
        // 微信号规则：6-20位，字母开头，可包含字母、数字、下划线、减号
        String wechatPattern = "^[a-zA-Z][a-zA-Z0-9_-]{5,19}$";
        return Pattern.matches(wechatPattern, wechat.trim());
    }
    
    /**
     * 验证银行卡号
     * @param bankCard 银行卡号
     * @return 是否有效
     */
    public static boolean isValidBankCard(String bankCard) {
        if (isEmpty(bankCard)) {
            return false;
        }
        
        String cleanCard = bankCard.trim().replaceAll("\\s+", "");
        
        // 银行卡号一般为13-19位数字
        String bankCardPattern = "^\\d{13,19}$";
        if (!Pattern.matches(bankCardPattern, cleanCard)) {
            return false;
        }
        
        // 使用Luhn算法验证
        return validateLuhn(cleanCard);
    }
    
    /**
     * 验证中文姓名
     * @param name 姓名
     * @return 是否有效
     */
    public static boolean isValidChineseName(String name) {
        if (isEmpty(name)) {
            return false;
        }
        
        // 中文姓名：2-10个中文字符，可包含·
        String namePattern = "^[\\u4e00-\\u9fa5·]{2,10}$";
        return Pattern.matches(namePattern, name.trim());
    }
    
    /**
     * 验证身份证校验码
     * @param idCard 身份证号
     * @return 校验码是否正确
     */
    private static boolean validateIdCardChecksum(String idCard) {
        if (idCard.length() != 18) {
            return false;
        }
        
        // 权重因子
        int[] weights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        // 校验码对应值
        char[] checkCodes = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
        
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += Character.getNumericValue(idCard.charAt(i)) * weights[i];
        }
        
        int mod = sum % 11;
        char expectedCheckCode = checkCodes[mod];
        char actualCheckCode = idCard.charAt(17);
        
        return expectedCheckCode == actualCheckCode;
    }
    
    /**
     * Luhn算法验证（用于银行卡号验证）
     * @param cardNumber 卡号
     * @return 是否通过验证
     */
    private static boolean validateLuhn(String cardNumber) {
        int sum = 0;
        boolean alternate = false;
        
        for (int i = cardNumber.length() - 1; i >= 0; i--) {
            int digit = Character.getNumericValue(cardNumber.charAt(i));
            
            if (alternate) {
                digit *= 2;
                if (digit > 9) {
                    digit = (digit % 10) + 1;
                }
            }
            
            sum += digit;
            alternate = !alternate;
        }
        
        return sum % 10 == 0;
    }
    
    /**
     * 验证邮政编码
     * @param zipCode 邮政编码
     * @return 是否有效
     */
    public static boolean isValidZipCode(String zipCode) {
        if (isEmpty(zipCode)) {
            return false;
        }
        
        // 中国邮政编码为6位数字
        String zipPattern = "^\\d{6}$";
        return Pattern.matches(zipPattern, zipCode.trim());
    }
    
    /**
     * 验证车牌号
     * @param licensePlate 车牌号
     * @return 是否有效
     */
    public static boolean isValidLicensePlate(String licensePlate) {
        if (isEmpty(licensePlate)) {
            return false;
        }
        
        // 普通车牌：省份简称+字母+5位数字或字母
        // 新能源车牌：省份简称+字母+6位数字或字母（包含绿牌）
        String platePattern = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]?$";
        return Pattern.matches(platePattern, licensePlate.trim());
    }
    
    /**
     * 验证密码是否正确
     * @param rawPassword 明文密码
     * @param encodedPassword 加密后的密码
     * @return 是否匹配
     */
    public static boolean validatePassword(String rawPassword, String encodedPassword) {
        if (isEmpty(rawPassword) || isEmpty(encodedPassword)) {
            return false;
        }
        
        // 简单实现：实际项目中应该使用更安全的密码验证方式
        return encodedPassword.equals(encodePassword(rawPassword));
    }
    
    /**
     * 对密码进行编码
     * @param password 明文密码
     * @return 编码后的密码
     */
    public static String encodePassword(String password) {
        if (isEmpty(password)) {
            return "";
        }
        
        try {
            // 使用SHA-256进行哈希
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(password.getBytes(StandardCharsets.UTF_8));
            
            // 转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hashBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            // 如果SHA-256不可用，使用简单的替代方案
            return "encoded_" + password;
        }
    }
}